package taskhandler

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"os"
	"strconv"
	"strings"

	"cvevulner/common"
	"cvevulner/models"
	"cvevulner/util"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/config"
	"github.com/astaxie/beego/logs"
)

const (
	//GiteOrgInfoURL get gitee org info url
	GiteOrgInfoURL = `https://gitee.com/api/v5/orgs/%v?access_token=%v`
	//GiteOrgReposURL get all repository url
	GiteOrgReposURL = `https://gitee.com/api/v5/orgs/%v/repos?access_token=%v&type=all&page=%v&per_page=%v`
	//GiteRepoIssuesURL get issue list url
	GiteRepoIssuesURL = `https://gitee.com/api/v5/repos/%v/%v/issues?access_token=%v&state=%v&sort=created&direction=desc&page=%v&per_page=%v`
	//GiteRepoBranch get repo branch url
	GiteRepoBranch = `https://gitee.com/api/v5/repos/%v/%v/branches?access_token=%v`
	//RepoInfoURL get repo info url
	RepoInfoURL = "https://api.openeuler.org/pkgmanage/packages/packageInfo?table_name=openEuler_LTS_20.03&pkg_name=%s"
	perPage     = 50
	//IssueType Types of issues crawled
	CIssueType         = "CVE和安全问题"
	GaussIssueType     = "缺陷"
	MindSporeIssueType = "Bug-Report"
	BranchRep          = `(\(.*\))|(（.*）)`
)

type GiteeToken struct {
	GrantType    string
	UserName     string
	Password     string
	ClientID     string
	ClientSecret string
	Scope        string
}

type IssueOptions struct {
	Token         string `json:"access_token"`
	Repo          string `json:"repo"`
	Title         string `json:"title"`
	IssueType     string `json:"issue_type"`
	Body          string `json:"body"`
	Assignee      string `json:"assignee"`
	Labels        string `json:"labels"`
	SecurityHole  bool   `json:"security_hole"`
	Collaborators string `json:"collaborators,omitempty"`
	Program       string `json:"program,omitempty"`
	Milestone     int64  `json:"milestone,omitempty"`
}

const bodyTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s
 
二、漏洞分析结构反馈
 影响性分析说明：
  %v
 openEuler评分：
  %v
 受影响版本排查(受影响/不受影响)：
  %v
 修复是否涉及abi变化(是/否)：
  %v
`

const bodyUpTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 openEuler评分：
  %v
 Vector：CVSS：%v
 受影响版本排查(受影响/不受影响)：
  %v
 修复是否涉及abi变化(是/否)：
  %v
`
const bodySecLinkTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 openEuler评分：
  %v
 Vector：CVSS：%v
 受影响版本排查(受影响/不受影响)：
  %v
 修复是否涉及abi变化(是/否)：
  %v
三、漏洞修复
安全公告链接：%v
`

const commentCopyValue = `
%v
**issue处理注意事项:** 
**1. 当前issue受影响的分支提交pr时, 须在pr描述中填写当前issue编号进行关联, 否则无法关闭当前issue;**
**2. 模板内容需要填写完整, 无论是受影响或者不受影响都需要填写完整内容,未引入的分支不需要填写, 否则无法关闭当前issue;**
**3. 以下为模板中需要填写完整的内容, 请复制到评论区回复, 注: 内容的标题名称(影响性分析说明, openEuler评分, 受影响版本排查(受影响/不受影响), 修复是否涉及abi变化(是/否))不能省略,省略后cve-manager将无法正常解析填写内容.**
************************************************************************
影响性分析说明: 


openEuler评分: (评分和向量)


受影响版本排查(受影响/不受影响): 
%v
修复是否涉及abi变化(是/否)：
%v
-----------------------------------------------------------------------
issue处理具体操作请参考: 
%v
pr关联issue具体操作请参考:
%v
`

const gaussBodyTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 openGauss评分：
  %v
 受影响版本排查(受影响/不受影响)：
  %v
`

const SporeBodyTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 MindSpore评分：
  %v
 受影响版本排查(受影响/不受影响)：
  %v
`

const gaussBodyUpTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 openGauss评分：
  %v
 Vector：CVSS：%v
 受影响版本排查(受影响/不受影响)：
  %v
`

const SporeBodyUpTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 MindSpore评分：
  %v
 Vector：CVSS：%v
 受影响版本排查(受影响/不受影响)：
  %v
`
const LooKengBodyTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 openLooKeng评分：
  %v
 受影响版本排查(受影响/不受影响)：
  %v
`
const LooKengBodyUpTpl = `一、漏洞信息
 漏洞编号：%v
 漏洞归属组件：%v
 漏洞归属的版本：%v
 CVSS V%v分值：
  BaseScore：%v
  Vector：CVSS：%v
 漏洞简述：
  %v
 漏洞公开时间：%v
 漏洞创建时间：%v
 漏洞详情参考链接：
  %v
 漏洞分析指导链接：
  %v
 漏洞数据来源:
  %v
 漏洞补丁信息：
  %s

二、漏洞分析结构反馈
 影响性分析说明：
  %v
 openLooKeng评分：
  %v
 Vector：CVSS：%v
 受影响版本排查(受影响/不受影响)：
  %v
`

const gaussCommentCopyValue = `
%v
**issue处理注意事项:** 
**1. 当前issue受影响的分支提交pr时, 须在pr描述中填写当前issue编号进行关联, 否则无法关闭当前issue;**
**2. 模板内容需要填写完整, 无论是受影响或者不受影响都需要填写完整内容,未引入的分支不需要填写, 否则无法关闭当前issue;**
**3. 以下为模板中需要填写完整的内容, 请复制到评论区回复, 注: 内容的标题名称(影响性分析说明, openGauss评分, 受影响版本排查(受影响/不受影响))不能省略,省略后cve-manager将无法正常解析填写内容.**
************************************************************************
影响性分析说明: 


openGauss评分: (评分和向量)


受影响版本排查(受影响/不受影响): 
%v
-----------------------------------------------------------------------
issue处理具体操作请参考: 
%v
pr关联issue具体操作请参考:
%v
`

const SporeCommentCopyValue = `
%v
**issue处理注意事项:** 
**1. 当前issue受影响的分支提交pr时, 须在pr描述中填写当前issue编号进行关联, 否则无法关闭当前issue;**
**2. 模板内容需要填写完整, 无论是受影响或者不受影响都需要填写完整内容,未引入的分支不需要填写, 否则无法关闭当前issue;**
**3. 以下为模板中需要填写完整的内容, 请复制到评论区回复, 注: 内容的标题名称(影响性分析说明, MindSpore评分, 受影响版本排查(受影响/不受影响))不能省略,省略后cve-manager将无法正常解析填写内容.**
************************************************************************
影响性分析说明: 


MindSpore评分: (评分和向量)


受影响版本排查(受影响/不受影响): 
%v
-----------------------------------------------------------------------
issue处理具体操作请参考: 
%v
pr关联issue具体操作请参考:
%v
`
const LooKengCommentCopyValue = `
%v
**issue处理注意事项:** 
**1. 当前issue受影响的分支提交pr时, 须在pr描述中填写当前issue编号进行关联, 否则无法关闭当前issue;**
**2. 模板内容需要填写完整, 无论是受影响或者不受影响都需要填写完整内容,未引入的分支不需要填写, 否则无法关闭当前issue;**
**3. 以下为模板中需要填写完整的内容, 请复制到评论区回复, 注: 内容的标题名称(影响性分析说明, openLooKeng评分, 受影响版本排查(受影响/不受影响))不能省略,省略后cve-manager将无法正常解析填写内容.**
************************************************************************
影响性分析说明: 


openLooKeng评分: (评分和向量)


受影响版本排查(受影响/不受影响): 
%v
-----------------------------------------------------------------------
issue处理具体操作请参考: 
%v
pr关联issue具体操作请参考:
%v
`

const PrIssueLink = "https://gitee.com/help/articles/4142"

// Create first comment
func CommentTemplate(assignee, commentCmd, affectedVersion, path string, assignLoginList []string) string {
	maintainerList, mainOk := models.QueryRepoAllMaintainer(path)
	assList := []string{}
	assigneeStr := ""
	if len(assignLoginList) > 0 {
		for _, v := range assignLoginList {
			assList = append(assList, "@"+v+" ")
		}
	} else {
		if mainOk && len(maintainerList) > 0 {
			for _, v := range maintainerList {
				assList = append(assList, "@"+v.MemberName+" ")
			}
		}
	}
	if len(assList) > 0 {
		assigneeStr = strings.Join(assList, ",")
	} else {
		assigneeStr = "@" + assignee
	}
	commentTemplate := fmt.Sprintf(commentCopyValue, assigneeStr, affectedVersion, affectedVersion, commentCmd, PrIssueLink)
	return commentTemplate
}

func SporeCommentTemplate(assignee, commentCmd, affectedVersion string) string {
	anName := []string{}
	reviewerList, rlerr := models.GetSporeSecurityReviewerList()
	if len(reviewerList) > 0 {
		for _, v := range reviewerList {
			anName = append(anName, "@"+v.NameSpace+" ")
		}
	} else {
		logs.Error("GetSporeSecurityReviewerList, rlerr: ", rlerr)
	}
	if len(anName) > 1 {
		assignee = strings.Join(anName, ",")
	} else {
		assignee = "@" + assignee + " "
	}
	commentTemplate := fmt.Sprintf(SporeCommentCopyValue, assignee, affectedVersion, commentCmd, PrIssueLink)
	return commentTemplate
}

func GaussCommentTemplate(assignee, commentCmd, affectedVersion string) string {
	anName := []string{}
	reviewerList, rlerr := models.GetGuassSecurityReviewerList()
	if len(reviewerList) > 0 {
		for _, v := range reviewerList {
			anName = append(anName, "@"+v.NameSpace+" ")
		}
	} else {
		logs.Error("GetGuassSecurityReviewerList, rlerr: ", rlerr)
	}
	if len(anName) > 1 {
		assignee = strings.Join(anName, ",")
	} else {
		assignee = "@" + assignee + " "
	}
	commentTemplate := fmt.Sprintf(gaussCommentCopyValue, assignee, affectedVersion, commentCmd, PrIssueLink)
	return commentTemplate
}

func LooKengCommentTemplate(assignee, commentCmd, affectedVersion string) string {
	anName := []string{}
	reviewerList, rlerr := models.GetOpenLookengSecurityReviewerList()
	if len(reviewerList) > 0 {
		for _, v := range reviewerList {
			anName = append(anName, "@"+v.NameSpace+" ")
		}
	} else {
		logs.Error("GetOpenLookengSecurityReviewerList, rlerr: ", rlerr)
	}
	if len(anName) > 1 {
		assignee = strings.Join(anName, ",")
	} else {
		assignee = "@" + assignee + " "
	}
	commentTemplate := fmt.Sprintf(LooKengCommentCopyValue, assignee, affectedVersion, commentCmd, PrIssueLink)
	return commentTemplate
}

func GitOpenEulerData(values map[string]interface{}, ge *models.GitOpenEuler, tb models.GitPackageTable) {
	defer common.Catchs()
	ge.TableName = tb.TableName
	ge.TableId = tb.TableId
	ge.Status = 1
	if values["feature"] == nil {
		ge.Feature = ""
	} else {
		switch values["feature"].(type) {
		case string:
			ge.Feature = values["feature"].(string)
		case int:
			ge.Feature = strconv.Itoa(values["feature"].(int))
		case int64:
			ge.Feature = strconv.FormatInt(values["feature"].(int64), 10)
		case float64:
			ge.Feature = strconv.FormatInt(int64(values["feature"].(float64)), 10)
		default:
			ge.Feature = ""
		}
	}
	if values["url"] == nil {
		ge.OriginUrl = ""
	} else {
		ge.OriginUrl = values["url"].(string)
	}
	switch values["id"].(type) {
	case string:
		ge.PackageId, _ = strconv.ParseInt(values["id"].(string), 10, 64)
	case int:
		ge.PackageId = values["id"].(int64)
	case int64:
		ge.PackageId = values["id"].(int64)
	case float64:
		ge.PackageId = int64(values["id"].(float64))
	default:
		ge.PackageId = 0
	}
	if values["name"] == nil {
		ge.PackageName = ""
	} else {
		packName := values["name"].(string)
		if packName != "" {
			packName = common.DeletePreAndSufSpace(packName)
		}
		ge.PackageName = packName
	}
	if values["version"] == nil {
		ge.Version = ""
	} else {
		version := values["version"].(string)
		if version != "" {
			version = common.DeletePreAndSufSpace(version)
		}
		ge.Version = version
	}
	if values["release"] == nil {
		ge.Release = ""
	} else {
		release := values["release"].(string)
		if release != "" {
			release = common.DeletePreAndSufSpace(release)
		}
		ge.Release = release
	}
	if values["rpm_license"] == nil {
		ge.License = ""
	} else {
		ge.License = values["rpm_license"].(string)
	}
	if values["maintainer"] == nil {
		ge.MainTainer = ""
	} else {
		ge.MainTainer = values["maintainer"].(string)
	}
	if values["maintainlevel"] == nil {
		ge.MainTainLevel = 0
	} else {
		ge.MainTainLevel = values["maintainlevel"].(int8)
	}
	if values["release_time"] == nil {
		ge.ReleaseTime = ""
	} else {
		ge.ReleaseTime = values["release_time"].(string)
	}
	switch values["used_time"].(type) {
	case string:
		ge.UsedTime = values["used_time"].(string)
	case int:
		ge.UsedTime = strconv.Itoa(values["used_time"].(int))
	case int64:
		ge.UsedTime = strconv.FormatInt(values["used_time"].(int64), 10)
	case float64:
		ge.UsedTime = strconv.FormatInt(int64(values["used_time"].(float64)), 10)
	default:
		ge.UsedTime = ""
	}
	if values["latest_version"] == nil {
		ge.LatestVersion = ""
	} else {
		ge.LatestVersion = values["latest_version"].(string)
	}
	if values["latest_version_time"] == nil {
		ge.LatestVersionTime = ""
	} else {
		ge.LatestVersionTime = values["latest_version_time"].(string)
	}
	switch values["issue"].(type) {
	case string:
		ge.IssueCount, _ = strconv.ParseInt(values["issue"].(string), 10, 64)
	case int:
		ge.IssueCount = values["issue"].(int64)
	case int64:
		ge.IssueCount = values["issue"].(int64)
	case float64:
		ge.IssueCount = int64(values["issue"].(float64))
	default:
		ge.IssueCount = 0
	}
}

func GitOpenEulerInfoData(values map[string]interface{}, gp *models.GitPackageInfo, ge models.GitOpenEuler) {
	defer common.Catchs()
	gp.GitId = ge.GitId
	gp.Ids = 0
	if values["pkg_name"] == nil {
		gp.PackageName = ""
	} else {
		PackageName := values["pkg_name"].(string)
		if PackageName != "" {
			PackageName = common.DeletePreAndSufSpace(PackageName)
		}
		gp.PackageName = PackageName
	}
	if values["version"] == nil {
		gp.Version = ""
	} else {
		Version := values["version"].(string)
		if Version != "" {
			Version = common.DeletePreAndSufSpace(Version)
		}
		gp.Version = Version
	}
	if values["release"] == nil {
		gp.Release = ""
	} else {
		Release := values["release"].(string)
		if Release != "" {
			Release = common.DeletePreAndSufSpace(Release)
		}
		gp.Release = Release
	}
	if values["url"] == nil {
		gp.OriginUrl = ""
	} else {
		gp.OriginUrl = values["url"].(string)
	}
	if values["license"] == nil {
		gp.License = ""
	} else {
		gp.License = values["license"].(string)
	}
	switch values["feature"].(type) {
	case string:
		gp.Feature = values["feature"].(string)
	case int:
		gp.Feature = strconv.Itoa(values["feature"].(int))
	case int64:
		gp.Feature = strconv.FormatInt(values["feature"].(int64), 10)
	case float64:
		gp.Feature = strconv.FormatInt(int64(values["feature"].(float64)), 10)
	default:
		gp.Feature = ""
	}
	if values["maintainer"] == nil {
		gp.MainTainer = ""
	} else {
		gp.MainTainer = values["maintainer"].(string)
	}
	if values["maintainlevel"] == nil {
		gp.MainTainLevel = 0
	} else {
		gp.MainTainLevel = values["maintainlevel"].(int8)
	}
	if values["gitee_url"] == nil {
		gp.GitUrl = ""
	} else {
		gp.GitUrl = values["gitee_url"].(string)
	}
	if values["summary"] == nil {
		gp.Summary = ""
	} else {
		gp.Summary = values["summary"].(string)
	}
	if values["description"] == nil {
		gp.Decription = ""
	} else {
		gp.Decription = values["description"].(string)
	}
	BuildRequired := ""
	if values["buildrequired"].([]interface{}) != nil && len(values["buildrequired"].([]interface{})) > 0 {
		for _, vx := range values["buildrequired"].([]interface{}) {
			BuildRequired = BuildRequired + vx.(string) + ","
		}
		gp.BuildRequired = BuildRequired[:len(BuildRequired)-1]
	} else {
		gp.BuildRequired = BuildRequired
	}
	gp.Status = 0
}

type GitTablePackCount struct {
	Page      int
	Size      int
	TableName string
	Count     int64
}

func OrgRepoParams(path, brand string) string {
	index := -1
	if strings.Index(brand, ":") != -1 {
		index = strings.Index(brand, ":")
	} else if strings.Index(brand, "：") != -1 {
		index = strings.Index(brand, "：")
	}
	tmpBrandx := brand
	brandx := brand
	if index != -1 {
		brandx = brand[:index]
	}
	ori := models.QueryEulerOriginBRepo(path, brandx)
	if len(ori) > 0 {
		for _, or := range ori {
			if len(or.Branchs) > 0 {
				brSlice := strings.Split(or.Branchs, ",")
				if len(brSlice) > 0 {
					for _, br := range brSlice {
						if br == brandx {
							if len(or.Version) > 0 && len(or.Version) < 32 {
								if index != -1 {
									return brand[:index] + "(" + or.Version + ")" + brand[index:]
								}
								return brandx + "(" + or.Version + ")"
							}
						}
					}
				}
			}
		}
	}
	return tmpBrandx
}

func AffectVersionExtract(brandArray []string, itsAffectedVersion, packName string, organizationID int8) string {
	affectedVersion := ""
	if itsAffectedVersion != "" && len(itsAffectedVersion) > 0 {
		brandsGroup := strings.Split(itsAffectedVersion, ",")
		if len(brandsGroup) > 0 {
			for i, brand := range brandsGroup {
				if brand == "" || len(brand) < 2 {
					continue
				}
				brandx := ""
				if organizationID == 1 {
					brandx = common.BranchVersionRep(brand)
					brandx = OrgRepoParams(packName, brandx)
				} else {
					brandx = brand
				}
				//logs.Info("brand1: ", brandx)
				affectedVersion = affectedVersion + strconv.Itoa(i+1) + "." + brandx + "\n"
			}
		}
	} else {
		if len(brandArray) > 0 {
			for i, brand := range brandArray {
				if brand == "" || len(brand) < 2 {
					continue
				}
				brandx := ""
				if organizationID == 1 {
					brandx = common.BranchVersionRep(brand)
					brandx = OrgRepoParams(packName, brandx)
				} else {
					brandx = brand
				}
				logs.Info("brand2: ", brandx)
				affectedVersion = affectedVersion + strconv.Itoa(i+1) + "." + brandx + ":\n"
			}
		} else {
			affectedVersion = "\n"
		}
	}
	logs.Info("affectedVersion: ", affectedVersion)
	return affectedVersion
}

func updateTemplateAbi(brandArray []string, its models.IssueTemplate) {
	cols := make([]string, 0)
	if len(its.AbiVersion) < 2 && len(brandArray) > 0 {
		abiVersionStr := ""
		for _, abi := range brandArray {
			abiVersionStr = abiVersionStr + abi + ":,"
		}
		if len(abiVersionStr) > 2 {
			its.AbiVersion = abiVersionStr[:len(abiVersionStr)-1]
			cols = append(cols, "AbiVersion")
		}
	}
	if len(its.AffectedVersion) < 2 && len(brandArray) > 0 {
		AffectedVersionStr := ""
		for _, ver := range brandArray {
			AffectedVersionStr = AffectedVersionStr + ver + ":,"
		}
		if len(AffectedVersionStr) > 2 {
			its.AffectedVersion = AffectedVersionStr[:len(AffectedVersionStr)-1]
			cols = append(cols, "AffectedVersion")
		}
	}
	if len(cols) > 0 {
		err := models.UpdateIssueTemplate(&its, cols...)
		if err != nil {
			logs.Error("updateTemplateAbi, UpdateIssueTemplate, err: ", updateTemplateAbi)
		}
	}
}

func AddLabelValue(accessToken, path, issueNum, owner, issueLabel string, flag int8) []string {
	tmpLabelSlice := make([]string, 0)
	if len(issueNum) > 1 {
		if flag == 1 {
			tmpLabelSlice, _ = QueryIssueLabels(accessToken, path, issueNum, owner)
		} else {
			_, tmpLabelSlice = QueryIssueLabels(accessToken, path, issueNum, owner)
		}
	}
	if len(issueLabel) > 1 {
		issueLabel := strings.Split(issueLabel, ",")
		for _, lab := range issueLabel {
			if len(tmpLabelSlice) > 0 {
				labFlag := false
				for _, labs := range tmpLabelSlice {
					if strings.ToUpper(labs) == strings.ToUpper(lab) {
						labFlag = true
						break
					}
				}
				if !labFlag {
					tmpLabelSlice = append(tmpLabelSlice, lab)
				}
			} else {
				tmpLabelSlice = append(tmpLabelSlice, lab)
			}
		}
	}
	labelSlice := make([]string, 0)
	labelSlice = common.RemoveDupString(tmpLabelSlice)
	return labelSlice
}

func CreateIssueBody(accessToken, owner, path, assignee string,
	cve models.VulnCenter, sc models.Score, openEulerScore, score, labels string,
	its models.IssueTemplate, flag int, issueType, pkgLink string, brandArray []string) string {
	requestBody := ""
	scoreType := ""
	if sc.ScoreType == "v2" {
		scoreType = "2.0"
	} else {
		scoreType = "3.0"
	}
	if len(brandArray) == 0 {
		if cve.OrganizationID == 1 || cve.OrganizationID == 2 {
			brandArray, _ = GetBranchesInfo(accessToken, owner, path, cve.OrganizationID)
		} else if cve.OrganizationID == 3 || cve.OrganizationID == 4 {
			brandArray = CreateBrandAndTags(accessToken, owner, path, cve.OrganizationID)
		}
	}
	if cve.Description != "" && len(cve.Description) > 1 {
		cve.Description = strings.Replace(cve.Description, "\n", "", -1)
		cve.Description = strings.ReplaceAll(cve.Description, "\"", " ")
		cve.Description = strings.ReplaceAll(cve.Description, "'", " ")
		cve.Description = strings.ReplaceAll(cve.Description, "\\", " ")
	}
	BConfig, err := config.NewConfig("ini", "conf/app.conf")
	if err != nil {
		logs.Error("config init error:", err)
		return ""
	}
	commentCmd := BConfig.String("reflink::comment_cmd")
	gaussCommentCmd := BConfig.String("reflink::gauss_comment_cmd")
	sporeCommentCmd := BConfig.String("reflink::spore_comment_cmd")
	looKengCommentCmd := BConfig.String("reflink::looKeng_comment_cmd")
	floatOpenEulerScore, err := strconv.ParseFloat(openEulerScore, 64)
	if err != nil {
		floatOpenEulerScore = 0.0
	}
	nvdScore, err := strconv.ParseFloat(score, 64)
	if err != nil {
		nvdScore = 0.0
	}
	cveAnalysis := ""
	if its.CveAnalysis != "" && len(its.CveAnalysis) > 1 {
		cveAnalysis = strings.Replace(its.CveAnalysis, "\n", "", -1)
		cveAnalysis = strings.ReplaceAll(cveAnalysis, "'", " ")
		cveAnalysis = strings.ReplaceAll(cveAnalysis, "\"", " ")
		cveAnalysis = strings.ReplaceAll(cveAnalysis, "\\", " ")
	}
	affectedVersion := AffectVersionExtract(brandArray, its.AffectedVersion, cve.PackName, cve.OrganizationID)
	abiVersion := AffectVersionExtract(brandArray, its.AbiVersion, cve.PackName, cve.OrganizationID)
	updateTemplateAbi(brandArray, its)
	logs.Info("its.CreateTime: ", its.CreateTime)
	updateTime := its.CreateTime.Format(common.DATE_FORMAT)
	if len(updateTime) >= 19 && its.TemplateId > 0 {
		updateTime = common.TimeConverStr(updateTime[:19])
	} else {
		updateTime = common.GetLocalCurTime()
	}
	logs.Info("cve.UpdateTime.String(): ", updateTime, its.CreateTime, cve.CreateTime)
	if updateTime != "" && len(updateTime) > 19 {
		updateTime = updateTime[:19]
	}
	StatusName := ""
	if its.StatusName != "" && len(its.StatusName) > 1 {
		if its.StatusName == "待办的" || its.StatusName == "开启的" ||
			strings.ToLower(its.StatusName) == "open" {
			StatusName = "open"
		} else if its.StatusName == "进行中" || strings.ToLower(its.StatusName) == "started" ||
			strings.ToLower(its.StatusName) == "progressing" {
			StatusName = "progressing"
		} else if its.StatusName == "已完成" || strings.ToLower(its.StatusName) == "closed" {
			StatusName = "closed"
			if AffectVersion(its.AffectedVersion) == 2 {
				labels = beego.AppConfig.String("labelFixed")
			} else if AffectVersion(its.AffectedVersion) == 3 {
				labels = beego.AppConfig.String("labeUnaffected")
			}
		} else if its.StatusName == "已拒绝" || strings.ToLower(its.StatusName) == "rejected" {
			StatusName = "rejected"
			return ""
		} else if its.StatusName == "已挂起" || strings.ToLower(its.StatusName) == "suspended" {
			StatusName = "suspended"
			return ""
		} else {
			StatusName = its.StatusName
			return ""
		}
	}
	labelSlice := make([]string, 0)
	labelSlice = AddLabelValue(accessToken, path, its.IssueNum, owner, labels, 1)
	//labelSlice = append(labelSlice, labels)
	labels = strings.Join(labelSlice, ",")
	its.IssueLabel = labels
	tpErr := models.UpdateIssueTemplate(&its, "IssueLabel")
	if tpErr != nil {
		logs.Error(tpErr)
	}
	bodyUpTplx := bodyUpTpl
	bodyTplx := bodyTpl
	if cve.OrganizationID == 2 {
		bodyUpTplx = gaussBodyUpTpl
		bodyTplx = gaussBodyTpl
		commentCmd = gaussCommentCmd
	} else if cve.OrganizationID == 3 {
		bodyUpTplx = SporeBodyUpTpl
		bodyTplx = SporeBodyTpl
		commentCmd = sporeCommentCmd
	} else if cve.OrganizationID == 4 {
		bodyUpTplx = LooKengBodyUpTpl
		bodyTplx = LooKengBodyTpl
		commentCmd = looKengCommentCmd
	}
	cveNumber := "[" + cve.CveNum + "](https://nvd.nist.gov/vuln/detail/" + cve.CveNum + ")"
	cvePkg := fmt.Sprintf("[%s](https://gitee.com/%s/%s)", cve.PackName, owner, path)
	cveRepo := fmt.Sprintf("[%s](https://gitee.com/%s/%s)", cve.RepoName, owner, path)
	cve.CveDetailUrl = "https://nvd.nist.gov/vuln/detail/" + cve.CveNum
	cve.CveLevel = models.OpenEulerScoreProc(nvdScore)
	if len(cve.CveVersion) > 0 && cve.CveVersion[0] == ',' {
		cve.CveVersion = cve.CveVersion[1:]
	}
	mile := 0
	if cve.OrganizationID == 3 {
		cveList := strings.Split(cve.CveVersion, ",")
		if len(cveList) > 0 {
			for _, vl := range cveList {
				data, _ := models.GetMindSporeYamlAll(&models.MindSporeYaml{PackageName: cve.RepoName})
				for _, v := range data {
					version := strings.TrimSpace(string(util.Symbol.ReplaceAll([]byte(v.Version), []byte(""))))
					if v.Repo == cve.PackName && JudgeVersion(vl, version, v.Version) {
						mile = v.Milestone
						break
					}
				}
			}
		}
	}

	if flag == 1 {
		if floatOpenEulerScore > 0.0 || (its.OpenEulerVector != "" && len(its.OpenEulerVector) > 1) {
			nveScore := score + " " + cve.CveLevel
			nveVector := scoreType + "/" + sc.NvectorVule
			oVector := scoreType + "/" + its.OpenEulerVector
			body := ""
			if its.Status == 3 && len(its.SecLink) > 3 && cve.OrganizationID == 1 {
				body = fmt.Sprintf(bodySecLinkTpl, cveNumber, cvePkg, cve.CveVersion, scoreType, nveScore, nveVector,
					cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
					genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, oVector, affectedVersion, abiVersion, its.SecLink)
			} else {
				if cve.OrganizationID == 1 {
					body = fmt.Sprintf(bodyUpTplx, cveNumber, cvePkg, cve.CveVersion, scoreType, nveScore, nveVector,
						cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
						genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, oVector, affectedVersion, abiVersion)
				} else {
					body = fmt.Sprintf(bodyUpTplx, cveNumber, cveRepo, cve.CveVersion, scoreType, nveScore, nveVector,
						cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
						genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, oVector, affectedVersion)
				}
			}
			requestBody = fmt.Sprintf(`{"access_token": "%s","repo": "%s","title": "%s","state": "%s","body": "%s","assignee": "%s","labels": "%s","security_hole": "false"}`, accessToken, path, cve.CveNum, StatusName, body, assignee, labels)
		} else {
			nveScore := score + " " + cve.CveLevel
			nveVector := scoreType + "/" + sc.NvectorVule
			openEulerScore = " "
			body := ""
			if cve.OrganizationID == 1 {
				body = fmt.Sprintf(bodyTplx, cveNumber, cvePkg, cve.CveVersion, scoreType, nveScore, nveVector,
					cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
					genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, affectedVersion, abiVersion)
			} else {
				body = fmt.Sprintf(bodyTplx, cveNumber, cveRepo, cve.CveVersion, scoreType, nveScore, nveVector,
					cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
					genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, affectedVersion)
			}
			requestBody = fmt.Sprintf(`{"access_token": "%s","repo": "%s","title": "%s","state": "%s","body": "%s","assignee": "%s","labels": "%s","security_hole": "false"}`, accessToken, path, cve.CveNum, StatusName, body, assignee, labels)
		}
	} else if flag == 2 {
		nveScore := score + " " + cve.CveLevel
		nveVector := scoreType + "/" + sc.NvectorVule
		openEulerScore = " "
		body := ""
		if cve.OrganizationID == 1 {
			body = fmt.Sprintf(bodyTplx, cveNumber, cvePkg, cve.CveVersion, scoreType, nveScore, nveVector,
				cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
				genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, affectedVersion, abiVersion)
		} else {
			body = fmt.Sprintf(bodyTplx, cveNumber, cveRepo, cve.CveVersion, scoreType, nveScore, nveVector,
				cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
				genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, affectedVersion)
		}

		issue := IssueOptions{Token: accessToken, Repo: path, Title: cve.CveNum, IssueType: issueType, Body: body, Assignee: assignee, Labels: labels, SecurityHole: false}
		if cve.OrganizationID == 3 {
			issue.Program = "67813"
			if assignee != "fangzhou0329" {
				issue.Collaborators = "fangzhou0329"
			}
			if mile != 0 {
				issue.Milestone = int64(mile)
			}
		}

		bys, _ := json.Marshal(&issue)
		requestBody = string(bys)
	} else {
		if floatOpenEulerScore > 0.0 || (its.OpenEulerVector != "" && len(its.OpenEulerVector) > 1) {
			nveScore := score + " " + cve.CveLevel
			nveVector := scoreType + "/" + its.NVDVector
			oVector := scoreType + "/" + its.OpenEulerVector
			body := ""
			if its.Status == 3 && len(its.SecLink) > 3 && cve.OrganizationID == 1 {
				body = fmt.Sprintf(bodySecLinkTpl, cveNumber, cvePkg, cve.CveVersion, scoreType, nveScore, nveVector,
					cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
					genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, oVector, affectedVersion, abiVersion, its.SecLink)
			} else {
				if cve.OrganizationID == 1 {
					body = fmt.Sprintf(bodyUpTplx, cveNumber, cvePkg, cve.CveVersion, scoreType, nveScore, nveVector,
						cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
						genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, oVector, affectedVersion, abiVersion)
				} else {
					body = fmt.Sprintf(bodyUpTplx, cveNumber, cveRepo, cve.CveVersion, scoreType, nveScore, nveVector,
						cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
						genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, oVector, affectedVersion)
				}
			}
			requestBody = fmt.Sprintf(`{"access_token": "%s","repo": "%s","title": "%s","state": "%s","body": "%s","assignee": "%s","labels": "%s","security_hole": "false"}`, accessToken, path, cve.CveNum, StatusName, body, its.Assignee, labels)
		} else {
			openEulerScore = " "
			nveScore := score + " " + cve.CveLevel
			nveVector := scoreType + "/" + sc.NvectorVule
			body := ""
			if cve.OrganizationID == 1 {
				body = fmt.Sprintf(bodyTplx, cveNumber, cvePkg, cve.CveVersion, scoreType, nveScore, nveVector,
					cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
					genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, affectedVersion, abiVersion)
			} else {
				body = fmt.Sprintf(bodyTplx, cveNumber, cveRepo, cve.CveVersion, scoreType, nveScore, nveVector,
					cve.Description, cve.RepairTime, updateTime, cve.CveDetailUrl+"\n"+getCveDetail(cve.CveNum)+"\n", commentCmd, holeSource(cve.DataSource),
					genPatchInfo(cve.CveNum), cveAnalysis, openEulerScore, affectedVersion)
			}
			requestBody = fmt.Sprintf(`{"access_token": "%s","repo": "%s","title": "%s","state": "%s","body": "%s","assignee": "%s","labels": "%s","security_hole": "false"}`, accessToken, path, cve.CveNum, StatusName, body, its.Assignee, labels)
		}
	}
	return requestBody
}

func holeSource(sourceCode int8) string {
	if sourceCode == 1 {
		return "openBrain开源漏洞感知系统"
	}

	return "其它"
}

func genPatchInfo(cveNum string) string {
	tpl := `<details>
<summary>详情(点击展开)</summary>

%s
</details>`

	info, err := models.QueryCveOriginPatchInfo(cveNum)
	if err != nil {
		logs.Error("QueryCveOriginPatchInfo error: ", err)
	}

	content := genPathInfoContent(info)

	return fmt.Sprintf(tpl, content)
}

func genPathInfoContent(info []models.OriginUpstreamPatch) string {
	if len(info) == 0 {
		return "无"
	}

	th := `| 影响的包 | 修复版本 | 修复补丁 | 问题引入补丁 | 来源  |
| ------- | -------- | ------- | -------- | --------- |
`
	tc := `| %s | %s | %s | %s | %s |
`

	table := th
	for _, v := range info {
		table = table + fmt.Sprintf(tc, v.Package, v.FixVersion, v.FixPatch, v.BreakPatch, v.Source)
	}

	return table
}

func getCveDetail(cveNum string) string {
	tpl := `<details>
<summary>更多参考(点击展开)</summary>

%s
</details>`

	info, err := models.QueryCveOriginReference(cveNum)
	if err != nil {
		logs.Error("QueryCveOriginPatchInfo error: ", err)
	}

	content := getCveDetailContent(info)

	return fmt.Sprintf(tpl, content)
}

func getCveDetailContent(info []models.OriginUpstreamReference) string {
	if len(info) == 0 {
		return "无"
	}

	th := `| 参考来源 | 参考链接 | 来源链接 |
| ------- | -------- | -------- |
`
	tc := `| %s | %s | %s |
`

	table := th
	for _, v := range info {
		table = table + fmt.Sprintf(tc, v.Refsource, v.Url, v.SourceUrl)
	}

	return table
}

func AffectVersion(affectedVersion string) int {
	affectBranchsxList := make([]string, 0)
	affectValue := make([]string, 0)
	unaffectValue := make([]string, 0)
	unFixValue := make([]string, 0)
	flag := 1
	affectedBranchs := beego.AppConfig.String("cve::affected_branchs")
	if affectedBranchs != "" && len(affectedBranchs) > 0 {
		affectBranchsxList = strings.Split(affectedBranchs, ",")
	}
	if affectedVersion != "" && len(affectedVersion) > 1 {
		affectProductList := strings.Split(affectedVersion, ",")
		if len(affectProductList) > 0 {
			for _, brands := range affectProductList {
				branchSlice := []string{}
				if strings.Contains(brands, ":") {
					branchSlice = strings.Split(brands, ":")
				} else if strings.Contains(brands, "：") {
					branchSlice = strings.Split(brands, "：")
				}
				if len(affectBranchsxList) > 0 {
					for _, arr := range affectBranchsxList {
						if len(branchSlice) == 2 {
							affBrand := common.BranchVersionRep(branchSlice[0])
							if strings.TrimSpace(affBrand) == arr {
								if len(strings.TrimSpace(branchSlice[1])) > 1 {
									if strings.TrimSpace(branchSlice[1]) == "受影响" {
										affectValue = append(affectValue, arr)
									} else {
										unaffectValue = append(unaffectValue, arr)
									}
								} else {
									unFixValue = append(unFixValue, arr)
								}
							}
						} else {
							if len(branchSlice) > 0 {
								affBrand := common.BranchVersionRep(branchSlice[0])
								if strings.TrimSpace(affBrand) == arr {
									unFixValue = append(unFixValue, arr)
								}
							}
						}
					}
				}
			}
		}
	}
	if len(affectValue) > 0 && len(unFixValue) == 0 {
		flag = 2
	} else if len(unaffectValue) > 0 && len(affectValue) == 0 && len(unFixValue) == 0 {
		flag = 3
	}
	return flag
}

func RemoveSubstring(s string, subList []string) string {
	newStr := s
	if len(subList) > 0 {
		for _, sub := range subList {
			if strings.Contains(newStr, sub) {
				if sub == "</br><br>" {
					newStr = strings.ReplaceAll(newStr, sub, "")
				} else {
					newStr = strings.ReplaceAll(newStr, sub, " ")
				}

			}
		}
	}
	newStr = strings.TrimSpace(newStr)
	return newStr
}

func deleteTailBlank(str string) string {
	spaceNum := 0
	for i := len(str) - 1; i >= 0; i-- {
		if str[i] == ' ' {
			spaceNum++
		} else {
			break
		}
	}
	return str[:len(str)-spaceNum]
}

func IssueStateConversion(status int8) string {
	var retName string
	switch status {
	case 2:
		retName = "进行中"
	default:
		retName = "待办的"
	}
	return retName
}

func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func baseStdEncode(srcBtye []byte) string {
	encoding := base64.StdEncoding.EncodeToString(srcBtye)
	return encoding
}

func XmlSpecCharHand(xmlStr string) string {
	tempXmlStr := strings.ReplaceAll(xmlStr, "&", "&amp;")
	tempXmlStr = strings.ReplaceAll(tempXmlStr, "<", "&lt;")
	tempXmlStr = strings.ReplaceAll(tempXmlStr, ">", "&gt;")
	tempXmlStr = strings.ReplaceAll(tempXmlStr, "'", "&apos;")
	tempXmlStr = strings.ReplaceAll(tempXmlStr, "\"", "&quot;")
	return tempXmlStr
}

func GetOrganizationId(nameSpace string) (organizationID int8) {
	communityName := beego.AppConfig.String("communityName")
	if len(communityName) > 1 {
		communityList := strings.Split(communityName, ",")
		for _, cl := range communityList {
			cli := strings.Split(cl, ":")
			if len(cli) > 1 && nameSpace == cli[0] {
				id, ok := strconv.Atoi(cli[1])
				if ok == nil {
					organizationID = int8(id)
				}
			}
		}
	}
	return
}

// Query label
func QueryIssueLabels(token, repo, issueNum, owner string) ([]string, []string) {
	allLabelSlice := make([]string, 0)
	labelSlice := make([]string, 0)
	totalLabel := beego.AppConfig.String("totallabel")
	totalLabelList := strings.Split(totalLabel, ",")
	url := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/%v/issues/%v/labels?access_token=%v", owner, repo, issueNum, token)
	labelData, err := util.HTTPGet(url)
	if err == nil && labelData != nil {
		for _, value := range labelData {
			if _, ok := value["id"]; !ok {
				logs.Error("labelData, err: ", ok, "url: ", url)
				continue
			}
			labelStr := value["name"].(string)
			allLabelSlice = append(allLabelSlice, labelStr)
			labFlag := false
			for _, lab := range totalLabelList {
				if strings.ToUpper(labelStr) == strings.ToUpper(lab) {
					labFlag = true
					break
				}
			}
			if !labFlag {
				labelSlice = append(labelSlice, labelStr)
			}
		}
	}
	return labelSlice, allLabelSlice
}

// Add, change, delete tags
func UpdateIssueLabels(token, repo, issueNum, owner, label string) bool {
	labelStr := label
	labelSlice := strings.Split(label, ",")
	if len(labelSlice) > 0 {
		laSlice := []string{}
		for _, la := range labelSlice {
			laSlice = append(laSlice, fmt.Sprintf("\"%v\"", la))
		}
		if len(laSlice) > 0 {
			labelStr = strings.Join(laSlice, ",")
		}
	}
	url := fmt.Sprintf("https://gitee.com/api/v5/repos/%v/%v/issues/%v/labels?access_token=%v", owner, repo, issueNum, token)
	reqBody := fmt.Sprintf("[%v]", labelStr)
	logs.Info("UpdateIssueLabels, reqBody: ", reqBody)
	resp, err := util.HTTPPut(url, reqBody)
	if err != nil {
		logs.Error("UpdateIssueLabels, Failed to update label, url: ", url, ", err: ", err)
		return false
	}
	if resp == nil || len(resp) == 0 {
		return true
	}
	if _, ok := resp[0]["id"]; !ok {
		logs.Error("UpdateIssueLabels, Failed to update label, err: ", ok, ", url: ", url)
		return false
	}
	return true
}

func RegMatchCve(str string) string {
	reg := util.RegMatchCve
	if reg == nil {
		fmt.Println("RegMatchCve err")
		return ""
	}
	reslist := reg.FindAllString(str, -1)
	if len(reslist) > 0 {
		return reslist[0]
	} else {
		return ""
	}
}
